/**
 * 树搜索
 *  params:
 *  treeOriginData(必填)：树的源数据，可以理解为渲染页面树的备份数据
 *  searchData(必填)：需要被匹配的文本，可以理解为搜索框中的用户输入
 *  matchKey(必填)：指定树源数据中通过那一个key去匹配searchData
 *  return:
 *  搜索后的数据
 */
export function treeSearch(
  treeOriginData,
  searchData,
  matchKey = "label",
  idKey = "tId",
  pidKey = "tPid",
  rootVal = "root"
) {
  //第一次遍历，添加key、提取匹配到的数据项id、以及父节点id
  let treeData = JSON.parse(JSON.stringify(treeOriginData));
  let targetIdTotal = [];
  let targetIdPath = [];
  let targetIdMatch = [];
  let fn = (array, level = -1, pId = rootVal, parent = []) => {
    // console.warn(array, level, pId, parent);
    let lv = level;
    lv++;
    for (let i = 0; i < array.length; i++) {
      let item = array[i];
      item[idKey] = "tree_" + parseInt(Math.random() * 1000000);
      item[pidKey] = pId;

      item.path = JSON.parse(JSON.stringify(parent));
      if (item[matchKey].includes(searchData)) {
        targetIdPath.push(...item.path);
        targetIdMatch.push(item[idKey]);
      }
      if (item.children) {
        let path_ = JSON.parse(JSON.stringify(item.path));
        path_.push(item[idKey]);
        fn(item.children, lv, item[idKey], path_);
      }
    }
  };
  fn(treeData);
  targetIdTotal = [...targetIdPath, ...targetIdMatch];

  //第二次遍历、过滤
  let fn2 = (array) => {
    let newArr = [];
    for (let j = 0; j < array.length; j++) {
      let item = array[j];
      if (targetIdTotal.includes(item[idKey])) {
        //删除添加的key
        delete item[idKey];
        delete item[pidKey];
        delete item.path;
        newArr.push(item);
        //如果匹配项有child,child直接全部存入。
        //如果是父节点的child,该child需要过滤
        if (item.children && !targetIdMatch.includes(item[idKey])) {
          item.children = fn2(item.children);
        }
      }
    }
    return newArr;
  };
  let treeDataTarget = fn2(treeData);

  //重新赋值
  return treeDataTarget;
}

/**
 * 判断数据类型
 * 支持以下9种数据类型检验
 * 数值     Number
 * 字符串   String
 * 对象     Object
 * 数组     Array
 * 布尔值   Boolean
 * 时间     Date
 * 函数     Function
 * undefined Undefined
 * null     Null
 * param:
 * data：数据变量
 * return:
 * 数据类型
 */
export function checkType(data) {
  let type = Object.prototype.toString.call(data);
  // console.warn("type", type);
  let newType;
  switch (type) {
    case "[object Number]":
      newType = "Number";
      break;

    case "[object String]":
      newType = "String";
      break;

    case "[object Object]":
      newType = "Object";
      break;

    case "[object Array]":
      newType = "Array";
      break;

    case "[object Boolean]":
      newType = "Boolean";
      break;

    case "[object Date]":
      newType = "Date";
      break;

    case "[object Function]":
      newType = "Function";
      break;

    case "[object Undefined]":
      newType = "Undefined";
      break;

    case "[object Null]":
      newType = "Null";
      break;
  }
  // console.warn("newType", newType);
  return newType;
}

/**
 * Array<object>去重
 * param:
 * array：数组
 * key：指定根据那个key的值去重
 * return:
 * 去重后的数组
 */
export function arrayDeduplyObject(array, key) {
  if (!Object.prototype.toString.call(array) == "[object Array]") {
    console.error("not array");
    return;
  }
  let temp = [];
  let newArr = [];
  for (let i = 0; i < array.length; i++) {
    let item = array[i];
    if (!temp.includes(item[key])) {
      temp.push(item[key]);
      newArr.push(item);
    }
  }
  return newArr;
}

/**
 * Array<string/number>去重
 * param:
 * array：数组
 * return:
 * 去重后的数组
 */
export function arrayDeduply(array) {
  if (!Object.prototype.toString.call(array) == "[object Array]") {
    console.error("not array");
    return;
  }
  let newArr = Array.from(new Set(array));
  return newArr;
}

/**
 * 引用数据类型深拷贝
 * 目前仅支持引用数据类型Object、Array实现深拷贝
 */
export function clone(data) {
  let type = Object.prototype.toString.call(data);
  if (type == "[object Object]") {
    let newData = {};
    Object.keys(data).forEach((key) => {
      if (typeof data[key] == "object") {
        newData[key] = clone(data[key]);
      } else {
        newData[key] = data[key];
      }
    });
    return newData;
  } else if (type == "[object Array]") {
    let newData = [];
    for (let i = 0; i < data.length; i++) {
      let item = data[i];
      if (typeof item == "object") {
        newData[i] = clone(item);
      } else {
        newData[i] = item;
      }
    }
    return newData;
  } else {
    return data;
  }
}

/**
 * 数字处理函数
 */
export function numberFormat(number, sliceLength, str, isInit) {
  //整数部分
  let numberArr = String(number).split(".");
  let init = numberArr[0];
  let sliceArrTotal = [];
  let sliceArr = [];
  let newNumber;
  for (let i = init.length - 1; i >= 0; i--) {
    let item = init[i];
    if (sliceArr.length == +sliceLength) {
      sliceArrTotal.unshift(sliceArr.join(""));
      sliceArr = [];
      sliceArr.unshift(item);
    } else {
      sliceArr.unshift(item);
    }
  }
  sliceArrTotal.unshift(sliceArr.join(""));
  newNumber = sliceArrTotal.join(str);
  //小数部分
  let decimal = numberArr[1];
  let newDecimal;
  if (Object.prototype.toString.call(isInit) == "[object Boolean]") {
    if (isInit) {
      newDecimal = "." + decimal;
    } else {
      newDecimal = "";
    }
  } else if (Object.prototype.toString.call(isInit) == "[object Number]") {
    if (decimal.length <= isInit) {
      newDecimal = decimal;
    } else {
      let base = Math.pow(10, decimal.length - isInit);
      newDecimal = Math.round(decimal / base);
    }
    newDecimal = "." + newDecimal;
  }
  return newNumber + newDecimal;
}

/**
 *  渲染dom后的回调函数
 */
export function renderCallback(selector, callback) {
  setTimeout(() => {
    // 启动计时器
    console.time("time");
    let i = 0;
    let fun = () => {
      i++;
      let dom = document.querySelector(`${selector}`);
      if (!dom) {
        requestAnimationFrame(fun);
      } else {
        // 停止计时，输出时间
        console.timeEnd("time");
        console.log("count", i);
        cancelAnimationFrame(fun);
        //异步执行
        setTimeout(() => {
          callback && callback(dom);
        }, 60);
      }
    };
    fun();
  }, 60);
}

/**
 * 生成指定长度（默认11位）的a-z+0-9混合的随机字符串
 * */
export function createRandomStrAndNum(length = 11) {
  const buf = new Uint8Array(length);
  window.crypto.getRandomValues(buf); //仅在浏览器中可以用
  console.log(buf);
  return Array.from(buf)
    .map((b) => b.toString(36).padStart(2, "0"))
    .join("")
    .substring(0, length);
}

/**
 * 生成指定长度（默认11位）的a-z的随机字符串
 * */
export function createRandomStr(length = 11) {
  return Array.from({ length })
    .map(() => {
      return String.fromCharCode(97 + Math.floor(Math.random() * 26));
    })
    .join("");
}

/**
 *  纬经度转度分秒
 * value {string} 120.2344443
 */
export function latLngToDMS(value) {
  val = value.toString();
  if (typeof val == "undefined" || val == "") {
    return "";
  }
  var i = val.indexOf(".");
  var strDu = i < 0 ? val : val.substring(0, i);
  var strFen = 0;
  var strMiao = 0;
  if (i > 0) {
    console.warn(" val.substring(i)", val.substring(i));
    var strFen = "0" + val.substring(i); //.343222  ===>  0.343222
    strFen = strFen * 60 + "";
    i = strFen.indexOf(".");
    if (i > 0) {
      strMiao = "0" + strFen.substring(i);
      strFen = strFen.substring(0, i);
      strMiao = strMiao * 60 + "";
      i = strMiao.indexOf(".");
      strMiao = strMiao.substring(0, i + 4);
      strMiao = parseFloat(strMiao).toFixed(2);
    }
  }
  return strDu + "°" + strFen + "'" + strMiao + '"';
}
console.warn("latLngToDMS(12.343222);", latLngToDMS(120.343222));

/**
 * 度分秒转纬经度
 * value {string} 120°20'35.60"传120-20-35.60
 * number {number} 设置保留几位小数，默认5位小数
 */
export function dMSToLatLng(value, number = 5) {
  val = value.toString();
  console.warn(`40°30'20"`, val);
  let Degrees = +val.split("-")[0];
  let MinutesToDegrees = +val.split("-")[1] / 60;
  let SecondsToDegrees = +val.split("-")[2] / 3600;
  let total = Degrees + MinutesToDegrees + SecondsToDegrees;
  // console.warn("total", total);
  let i = total.toString().indexOf(".");
  // console.warn("i", i);
  total = total.toString().substring(0, i + number + 1);
  // console.warn("total", total);
  return +total;
}
console.warn("dMSToLatLng", dMSToLatLng("120-20-35.60"));

export default {
  treeSearch,
  checkType,
  arrayDeduplyObject,
  arrayDeduply,
  clone,
  createRandomStrAndNum,
  createRandomStr,
  numberFormat,
  renderCallback,
  latLngToDMS,
  dMSToLatLng,
};
